package com.cjj.springsecurity.manager;

import com.cjj.springsecurity.entity.MyGrantedAuthorityUrlMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

/**
 * @author by BrownC_
 * @date 2021/12/21 14:45:11
 * @email ccc-ju@outlook.com
 */
@Component
@Slf4j
public class CustomerAccessDecisionManager implements AccessDecisionManager {

    private static final String ROLE_NEED_LOGIN = "ROLE_NEED_LOGIN";

    /**
     * 判断当前登录的用户是否具备当前请求URL所需要的角色信息
     * 如果不具备，就抛出 AccessDeniedException 异常，否则不做任何事即可
     *
     * @param authentication 当前登录用户的信息
     * @param object         FilterInvocation对象，可以获取当前请求对象
     * @param collection     FilterInvocationSecurityMetadataSource 中的 getAttributes() 方法的返回值，
     *                       即当前请求URL所需的角色
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        Collection<? extends GrantedAuthority> auths = authentication.getAuthorities();
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        for (ConfigAttribute configAttribute : collection) {
            if (ROLE_NEED_LOGIN.equals(configAttribute.getAttribute())) {
                //判断是否是匿名用户
                if (authentication instanceof AnonymousAuthenticationToken) {
                    log.info("匿名用户访问");
                    throw new AccessDeniedException("权限不足，无法访问");
                } else {
                    log.info("已登录用户访问");
                    return;
                }
            }
            for (GrantedAuthority authority : auths) {
                MyGrantedAuthorityUrlMethod grantedAuthorityUrlMethod = (MyGrantedAuthorityUrlMethod) authority;
                if (grantedAuthorityUrlMethod.getMethod().equals(request.getMethod()) && configAttribute.getAttribute().equals(authority.getAuthority())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足！");
    }

    /**
     * 是否支持校验
     * @param configAttribute 配置域
     * @return true | false
     */
    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    /**
     * 是否支持校验
     * @param aClass class
     * @return true | false
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
